#include "cwit_map.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define CWIT_MAP_DEFAULT_CAPACITY 5
void cwit_map_traversal(cwit_map *map,cwit_map_traversal_fun calbak)
{
    cwit_list_node* pCurrent = map->table_list.header.next;
	while (pCurrent != NULL)
    {
        cwit_map_dat *table =  pCurrent->data ;
        for(int i = 0; i < map->capacity;i++)
        {
            if(table[i].isuse)
            {
                calbak(table[i].index,table[i].indexSize,table[i].data,table[i].dataSize);
            }
        } 
        pCurrent = pCurrent->next;
    }
}
typedef enum __CWIT_MAP_GETKEY_RETURN{
    CWIT_MAP_KEY_NUSE = 0,
    CWIT_MAP_KEY_USE = 1,
    CWIT_MAP_KEY_NOFUND = 2
}CWIT_MAP_GETKEY_RETURN;
int cwit_map_getkey(cwit_map *map,void *index,int indexsize,unsigned long long int *selectkey,cwit_map_dat **ptable,int opt)
{
    if(map->capacity == 0)
    {
        map->capacity = CWIT_MAP_DEFAULT_CAPACITY;
    }
    //计算初始KEY
    // printf("getkey sss:%d %d \r\n",(int *)index,indexsize);
    unsigned long long int key = 0;
    for(int i = 0; i < indexsize; i++)
    {
        key += ((char *)index)[i];
    }
    key = (key % map->capacity)+1;
    //查找满足条件key
	cwit_list_node* pCurrent = map->table_list.header.next;
	while (pCurrent != NULL)
    {
        cwit_map_dat *table =  pCurrent->data ; 
        //查找数据
        for(int i = 0 ; i < 3; i++)
        {
            if((opt == 1)&& table[key].isuse == 0)
            {
                *selectkey = key;
                *ptable = &table[key];
                return CWIT_MAP_KEY_NUSE;//未使用key
            }
            else if((table[key].indexSize == indexsize) &&(memcmp(table[key].index,index,indexsize)==0))
            {
                // printf("indexsize is y\r\n");
                *selectkey = key;
                *ptable = &table[key];
                return CWIT_MAP_KEY_USE;//该索引已经存在
            }
            key = (key % map->capacity)+1;
        }
        pCurrent = pCurrent->next;
    }
    *selectkey = key;
    return CWIT_MAP_KEY_NOFUND; //需要重新创建一张表
}

void cwit_map_insert(cwit_map *map,void *index,int indexsize,void *data,int datasize)
{
    //参数检查
    if(map->capacity == 0)
    {
        map->capacity = CWIT_MAP_DEFAULT_CAPACITY;
    }
    unsigned long long int selectkey = 0;
    cwit_map_dat *table = NULL;
    switch (cwit_map_getkey(map,index,indexsize,&selectkey,&table,1))
    {
    case CWIT_MAP_KEY_NUSE://查找到符合要求的key
        table->index = malloc(indexsize);
        memset(table->index,0,indexsize);
        memcpy(table->index,index,indexsize);
        table->indexSize = indexsize;
        table->data = data;
        table->dataSize = datasize;
        table->isuse = 1;
        break;
    case CWIT_MAP_KEY_NOFUND:
        cwit_map_dat *tabledata = malloc(sizeof(cwit_map_dat) * map->capacity);
        memset(tabledata,0,sizeof(cwit_map_dat) * map->capacity);
        tabledata[selectkey].index = malloc(indexsize);
        memset(tabledata[selectkey].index,0,indexsize);
        memcpy(tabledata[selectkey].index,index,indexsize);
        tabledata[selectkey].data = data;
        tabledata[selectkey].isuse = 1;
        tabledata[selectkey].indexSize = indexsize;
        tabledata[selectkey].dataSize = datasize;
        cwit_list_push_tail(&map->table_list,tabledata);
        break;//需要重新创建表
    case CWIT_MAP_KEY_USE://该索引已经存在
        break;
    default:
        break;
    }
}
void* cwit_map_remove_key(cwit_map *map,void *index,int indexsize)
{
     unsigned long long int selectkey = 0;
    cwit_map_dat *table = NULL;
    switch (cwit_map_getkey(map,index,indexsize,&selectkey,&table,0))
    {
    case CWIT_MAP_KEY_NOFUND:
        return NULL;
    case CWIT_MAP_KEY_USE:
        table->isuse = 0;
        free(table->index);
        table->indexSize = 0;
        return table->data; 
    default:
        break;
    }
    return NULL;
}
void* cwit_map_get_value(cwit_map *map,void *index,int indexsize)
{
    unsigned long long int selectkey = 0;
    cwit_map_dat *table = NULL;
    switch (cwit_map_getkey(map,index,indexsize,&selectkey,&table,0))
    {
    case CWIT_MAP_KEY_NOFUND:
        return NULL;
    case CWIT_MAP_KEY_USE:
        return table->data;
    default:
        break;
    }
    return NULL;
}